#ifndef __VOL_UNRAR_DLL_H__
#define __VOL_UNRAR_DLL_H__

#include "unrar.h"

class CUnrarWrapper
{
	private:
		struct RAROpenArchiveDataEx m_OpenArchiveData;
		struct RARHeaderDataEx m_HeaderData;

		HANDLE m_File;

	public:
		CVolString m_PassWord;
		
		inline_ CUnrarWrapper() {
			m_File = NULL;
			memset(&m_HeaderData, 0, sizeof(m_HeaderData));
		}
		inline_ ~CUnrarWrapper() { if (m_File) RARCloseArchive(m_File); }
		
		void CloseRarFile ()
		{
			if (m_File)
			{
				RARCloseArchive(m_File);
				m_File = NULL;
			}
			memset(&m_OpenArchiveData, 0, sizeof(m_OpenArchiveData));
			memset(&m_HeaderData, 0, sizeof(m_HeaderData));
		}

		INT OpenFile(CVolString& fileName, CVolString& pass, LPARAM userData, UNRARCALLBACK callBack)
		{
			CloseRarFile ();
			
			if (!pass.IsEmpty())
				m_PassWord = pass;
			
			m_OpenArchiveData.ArcNameW = (wchar_t*)fileName.GetText();
			m_OpenArchiveData.OpenMode = RAR_OM_EXTRACT;
			
			wchar_t cmtBuf[16384];
			m_OpenArchiveData.CmtBufW = cmtBuf;
			m_OpenArchiveData.CmtBufSize = sizeof(cmtBuf) / sizeof(cmtBuf[0]);
			
			m_OpenArchiveData.Callback = callBack;
			m_OpenArchiveData.UserData = userData;
			
			m_File = RAROpenArchiveEx(&m_OpenArchiveData);
			
			if (m_File)
				RARReadHeaderEx(m_File, &m_HeaderData);
			
			return m_OpenArchiveData.OpenResult;
		}
		
		inline_ INT SkipFile() 
		{ 
			if (m_File == NULL)  return ERAR_EOPEN;
			INT ret = RARProcessFileW(m_File, RAR_SKIP, NULL, NULL);
			if (ret == ERAR_SUCCESS)
				return RARReadHeaderEx(m_File, &m_HeaderData);
			return ret;
		}
		
		inline_ INT TestFile() 
		{
			if (m_File == NULL)  return ERAR_EOPEN;
			INT ret = RARProcessFileW(m_File, RAR_TEST, NULL, NULL);
			if (ret == ERAR_SUCCESS)
				return RARReadHeaderEx(m_File, &m_HeaderData);
			return ret;
		}
		
		inline_ INT ExtractFile(CVolString& destPath) 
		{ 
			if (m_File == NULL)  return ERAR_EOPEN;
			INT ret = RARProcessFileW(m_File, RAR_EXTRACT, destPath.IsEmpty() ? NULL : (wchar_t *)destPath.GetText(), NULL);
			if (ret == ERAR_SUCCESS)
				return RARReadHeaderEx(m_File, &m_HeaderData);
			return ret;
		}
		
		inline_ wchar_t* GetArcName() { return m_HeaderData.ArcNameW; }
		inline_ wchar_t* GetFileName() { return m_HeaderData.FileNameW; }
		inline_ unsigned int GetFlags() { return m_HeaderData.Flags; }
		inline_ long long GetPackSize() { return ((long long)m_HeaderData.PackSize | ((long long)m_HeaderData.PackSizeHigh << 32)); }
		inline_ long long GetUnpSize() { return ((long long)m_HeaderData.UnpSize | ((long long)m_HeaderData.UnpSizeHigh << 32)); }
		inline_ unsigned int GetHostOS() { return m_HeaderData.HostOS; }
		inline_ unsigned int GetFileCRC() { return m_HeaderData.FileCRC; }
		inline_ unsigned int GetFileTime() { return m_HeaderData.FileTime; }
		inline_ unsigned int GetUnpVer() { return m_HeaderData.UnpVer; }
		inline_ unsigned int GetMethod() { return m_HeaderData.Method; }
		inline_ unsigned int GetFileAttr() { return m_HeaderData.FileAttr; }
		inline_ unsigned int GetDictSize() { return m_HeaderData.DictSize; }
		inline_ unsigned int GetHashType() { return m_HeaderData.HashType; }
		inline_ char* GetHash() { return m_HeaderData.Hash; }
		inline_ unsigned int GetRedirType() { return m_HeaderData.RedirType; }
		inline_ wchar_t* GetRedirName() { return m_HeaderData.RedirName; }
		inline_ unsigned int GetRedirNameSize() { return m_HeaderData.RedirNameSize; }
		inline_ unsigned int GetDirTarget() { return m_HeaderData.DirTarget; }
		inline_ unsigned int GetMtimeLow() { return m_HeaderData.MtimeLow; }
		inline_ unsigned int GetMtimeHigh() { return m_HeaderData.MtimeHigh; }
		inline_ unsigned int GetCtimeLow() { return m_HeaderData.CtimeLow; }
		inline_ unsigned int GetCtimeHigh() { return m_HeaderData.CtimeHigh; }
		inline_ unsigned int GetAtimeLow() { return m_HeaderData.AtimeLow; }
		inline_ unsigned int GetAtimeHigh() { return m_HeaderData.AtimeHigh; }
};

#endif
